// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
const { Configuration, ProgressPlugin } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
// const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader/dist/index.js')
const ESLintPlugin = require('eslint-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') //此插件将css打包成单独文件转为link引入。使用'style-loader'是将css打包在js中，再动态创建style标签，当网速慢时，请求js过慢容易造成白屏
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') //css压缩
const TerserWebpackPlugin = require('terser-webpack-plugin')
const os = require('os')
const threads = os.cpus().length

// console.log('cpu核数：=============>',threads)
/**
 * @type {Configuration}  //webpack配置智能语法提示
 */

// 用来获取处理样式的loader
function getStyleLoader(pre) {
  return [
    MiniCssExtractPlugin.loader, // 提取css成单独文件
    'css-loader', // 将css资源编译成commonjs的模块到js中
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: [
            'postcss-preset-env' // 能解决大多数样式兼容性问题。此时还需要在package.json里配置“browserslist”
          ]
        }
      }
    },
    pre
  ].filter(Boolean)
}

// console.log(__dirname) //项目路径
// console.log(process.cwd())//项目路径
// 函数中有两个参数(env,argv) => {}
module.exports = (env) => {
  // console.log('====>env:',env)
  // console.log('====>argv:',argv)
  return {
    mode: env.production ? 'production' : 'development',
    // mode:'development',
    entry: './src/main.ts',
    devServer: {
      port: 9000, // 指定端口
      compress: true, //压缩
      open: true, //自动打开浏览器 url 地址
      hot: true //热重载，热更新
    },
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'static/js/[name].[contenthash].js', //将js打包到static/js文件夹下
      hashDigestLength: 8, //hash值长度8位
      // 给打包输出的其他文件命名(分割的js)
      chunkFilename: 'static/js/[name].chunk.[contenthash].js',
      // 图片、字体等通过type:asset处理资源命名方式
      assetModuleFilename: 'static/media/[hash:8][ext][query]',
      clean: true //打包清空dist
    },
    devtool: env.production ? 'eval' : 'inline-source-map', //source map功能，可以将编译后的代码映射回源代码。可以提示具体哪个文件报错。会影响build和rebuild速度。
    resolve: {
      alias: {
        '@': path.resolve(__dirname, './src') //别名
      },
      extensions: ['.js', '.json', '.vue', '.ts'], //识别后缀（尽量减少条数，提高解析速度。因为他们会增加文件系统调用的次数）
      symlinks: false //不使用npm link 或者 yarn link时可以设置为false，提高解析速度
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          // vue-loader当前不支持放在oneOf中
          use: 'vue-loader'
        },
        {
          // 在文件匹配时，当命中其中一个，就不再继续匹配。减少匹配次数，提高性能
          oneOf: [
            {
              test: /\.css$/,
              use: getStyleLoader()
            },
            {
              test: /\.less$/,
              use: getStyleLoader('less-loader')
            },
            {
              test: /\.(png|svg|jpg|jpeg|gif)$/,
              type: 'asset',
              parser: {
                dataUrlCondition: {
                  //当图片小于200kb时，转为base64。这里仅做测试设置为200，正常应为一个比较小的值。
                  // 优点：减少网络请求，减轻服务器压力
                  // 缺点：资源变大
                  maxSize: 200 * 1024
                }
              }
              // generator:{  //通过assetModuleFilename统一设置
              //   //将图片资源打包到static/imgs文件夹下
              //   filename: "static/imgs/[hash:8][ext][query]",
              // }
            },
            {
              test: /\.(woff2?|ttf|mp3|mp4)$/,
              type: 'asset/resource' //导出源文件
              // generator:{  //通过assetModuleFilename统一设置
              //   //将其他资源打包到static/media文件夹下
              //   filename: "static/media/[hash:8][ext][query]",
              // }
            },
            {
              test: /\.ts$/,
              use: [
                {
                  loader: 'ts-loader',
                  options: {
                    configFile: path.resolve(__dirname, 'tsconfig.json'),
                    appendTsSuffixTo: [/\.vue$/]
                  }
                }
              ]
            },
            // babel将js语法降级，兼容低版本浏览器
            {
              test: /\.js$/,
              // exclude: /(node_modules)/, //排除node_modules
              include: path.resolve(__dirname, 'src'), //只对src中的文件做处理。应用于最少数量的必要模块，以提高性能。
              use: [
                {
                  loader: 'thread-loader',
                  options: {
                    works: threads //开启babel多进程编译
                  }
                },
                {
                  loader: 'babel-loader',
                  options: {
                    cacheDirectory: true, //babel编译使用.cache缓存，缓存文件在node_modules中的.cache
                    cacheCompression: false, //关闭缓存文件压缩
                    plugins: ['@babel/plugin-transform-runtime'] // 减少代码体积
                    // 将此预设写在.babelrc配置文件中
                    // presets: ['@babel/preset-env']
                  }
                }
              ]
            }
          ]
        }
      ]
    },
    plugins: [
      new htmlWebpackPlugin({
        // title:'webpack学习',
        // 模板：以public/index.html文件创建新的index.html文件。新html文件的特点：1、结构和原来一致。2、自动引入打包输出的资源
        template: path.resolve(__dirname, 'public/index.html')
        // filename:'index.html'//打包出的.html文件默认名字为index.html,可改为‘abc/adc.html’,则打包输出位置为abc文件夹下的abc.html文件
      }),
      new VueLoaderPlugin(), //解析vue
      // (percentage, message, ...args) => {} 回调函数中有三个参数
      new ProgressPlugin(),
      new ESLintPlugin({
        // 检测的文件类型
        extensions: ['.js', '.vue', '.ts'],
        // 检测哪些目录下的文件
        context: path.resolve(__dirname, 'src'),
        exclude: ['node_modules', 'dist'],
        threads: threads //开启eslint多进程检测
        // cache: true, // 开启缓存
        // // 缓存目录
        // cacheLocation: path.resolve(
        //   __dirname,
        //   "node_modules/.cache/.eslintcache"
        // ),
      }),
      new MiniCssExtractPlugin({
        filename: 'static/css/[name].[contenthash].css', //此处如果用hash名字的话，热更新的时候背景图片样式取值可能会取不到
        chunkFilename: 'static/css/[name].chunk.[contenthash].css'
      })

      // new FriendlyErrorsWebpackPlugin({
      //   compilationSuccessInfo:{
      //     messages:['You application is running here http://localhost:8080']
      //   }
      // })//美化webpack输出样式
    ],
    optimization: {
      // 压缩操作
      minimizer: [
        // `...`, //扩展出所有配置项(官网有说明)
        new CssMinimizerPlugin(), //压缩css
        // 压缩js。生产模式会默认开启TerserPlugin，但是我们需要进行其他配置，就要重新写了
        new TerserWebpackPlugin({
          parallel: threads // 开启多进程和设置进程数量
        })
      ],
      // 代码分割配置
      splitChunks: {
        chunks: 'all'
      }
    },
    stats: 'errors-only' //取消webpack提示,进一步清理终端输入
  }
}
